<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>02-构造函数的原型链</title>
</head>
<body>
    <script>
        // 可以理解为 构造函数的原型链会多一条
        // 数组的原型链跟构造函数差不多
        function app(name){
            this.name = name
        }
        // 同时具有 __proto__ 和 prototype 属性
        console.log( app.__proto__ ) // 指向 Function  function 类型
        console.log( app.prototype ) // 指向 原型对象  Object 类型
        var p = new app("haha")
        console.log(p)  // 实例
        console.log(p.__proto__)  // 实例的原型
        console.log(p.__proto__ == app.prototype)  // 实例的原型就是该构造函数的原型
        console.log(p.__proto__.__proto__)  // 实例原型的原型(构造函数原型的原型)就是一个对象
        console.log(p.__proto__.__proto__ == Object.prototype)  // true
        console.log(p.__proto__.__proto__.__proto__) //  null
        console.log('\n')

        // 函数套函数
        function app2(){

        }
        app2.prototype = new app()  // 让 app2 的原型，指向构造函数 app
        var obj = new app2()
        // 判断此时的原型链
        console.log(obj.__proto__.__proto__.__proto__ == Object.prototype) // true
        // obj 是 app2() 的实例
        console.log("aaa")
        console.log( obj.__proto__.__proto__ == app2.prototype.__proto__ ) //true
        
        console.log( obj.__proto__.__proto__ == app.prototype ) // true


        // 证明所有的对象，都是继承自同一个原型链
        var a = {}
        var b = {
            name:111
        }
        console.log(a.__proto__ == b.__proto__) // true
        console.log(a.__proto__ == Object.prototype) // true
        console.log(a.__proto__ == Object.prototype) // true

        console.log('\n下一个')
        var name = '最后一个测试'
        var qq1 = {
            name:'l',
            say:function(callback){
                console.log(callback ===arguments[0]) // true
                callback()  // 拿到全局的 '最后一个测试' 调用函数，与是否在哪个对象里面无关
                arguments[0]()  // undefind :由于 arguments 是对象，所以 arguments[0] 表示对象的一个属性，而这个属性对应的是一个方法 arguments[0]() 就表示方法的调用，而 arguments这个对象里面并没有 name属性，只有一个 qq2 的方法 , 里面的 this指向 arguments[0] 这个对象本身
            }
        }
        function qq2 (){console.log(this.name)}
        qq1.say(qq2)
        // 上下文模式的应用
        // var arr111 = [1,2,3,4,2,4,5,6,7,8,9,12,3,234,23423,423,4]
        // var qqqq = Math.max.apply(null,arr111)
        // console.log(qqqq)
    </script>
</body>
</html>